using System.Collections.Generic;
using NaughtyAttributes;
using SimpleJSON;
using UnityEngine;

namespace Gj
{
    public class DragListHelper : NodeHelper
    {
        public bool vertical;
        public bool horizontal;
        public bool allowOut;
        public bool allowDrag;
        public GameObject item;
        public GameObject content;
        public GameObject empty;

        public EaseType easeType;
        public float time;
        public int space;
        public int num;
        public bool isAuto;
        public bool isFull;
        public RectTransform rectTransform;
        public float top;
        public float bottom;
        public float left;
        public float right;

        public DragExitHelper exit;
        public List<DragItemHelper> list = new();
        private float _height;
        private int _itemNum;
        private float _width;
        protected DragItemHelper currentItem;

        protected bool isChange;
        private bool isExit;
        private bool isOut;
        private int tmpIndex = -1;

        protected override BindDataType bindDataType => BindDataType.List;

        [HideInInspector] public float width => rectTransform.rect.width;

        [HideInInspector] public float height => rectTransform.rect.height;

        protected override void BindData(JSONArray array)
        {
            if (list.Count == 0) isChange = true;
            for (var i = 0; i < array.Count; i++)
            {
                if (_itemNum <= i)
                {
                    var _item = ModelTools.Create(item, gameObject).GetComponent<DragItemHelper>();
                    _item.OnInit(this);
                    isChange = true;
                    _item.transform.SetSiblingIndex(i);
                    list.Insert(i, _item);
                }

                var obj = list[i];
                ItemHandle(i, obj.gameObject, array[i].AsObject);
            }

            if (_itemNum > array.Count)
            {
                isChange = true;
                for (var i = array.Count; i < _itemNum; i++)
                {
                    var item = list[i];
                    Destroy(item.gameObject);
                }

                list.RemoveRange(array.Count, list.Count - array.Count);
            }

            _itemNum = array.Count;
            if (num > 0)
            {
                if (list.Count > num)
                {
                    for (var i = num; i < list.Count; i++) Destroy(list[i].gameObject);
                    list.RemoveRange(num, list.Count - num);
                }
                else
                {
                    for (var i = list.Count; i < num; i++)
                    {
                        var _empty = ModelTools.Create(empty, gameObject).GetComponent<DragItemHelper>();
                        ItemHandle(-1, _empty.gameObject, new JSONObject());
                        _empty.OnInit(this);
                        list.Add(_empty);
                    }
                }
            }

            if (isChange && gameObject.activeSelf)
            {
                Refresh();
                if (list.Count > 0) allowDrag = num > 0 ? _itemNum > 0 : list.Count > 0;

                if (allowDrag)
                {
                    currentItem = list[0];
                    if (vertical)
                    {
                        var h = (height - currentItem.height) * SystemInput.scale / 2 * -1;
                        if (num > 0)
                        {
                            top = h + (_itemNum - 1) * currentItem.height * SystemInput.scale +
                                  (_itemNum - 1) * space * SystemInput.scale;
                            bottom = h;
                        }
                        else
                        {
                            top = h;
                            bottom = h * -1;
                        }
                    }

                    if (horizontal)
                    {
                        var w = (width - currentItem.width) * SystemInput.scale / 2 * -1;
                        if (num > 0)
                        {
                            left = w;
                            right = w + (_itemNum - 1) * currentItem.width * SystemInput.scale +
                                    (_itemNum - 1) * space * SystemInput.scale;
                        }
                        else
                        {
                            right = w;
                            left = w * -1;
                        }
                    }
                }
            }
        }

        protected void ItemHandle(int i, GameObject obj, JSONObject json)
        {
            var helper = obj.GetComponent<NodeHelper>();
            BindEvent(helper);
            helper.SetIndex(i);
            helper.SetData(json);
        }

        public void Check(int x, int y, int _in)
        {
            if (Out(x, y))
            {
                if (!isOut)
                {
                    isOut = true;
                    Remove(currentItem);
                    Refresh();
                    // _exit.gameObject.SetActive(true);
                }

                // if (Exit(x, y))
                // {
                //     isExit = true;
                //     _exit.Select();
                // }
                // else
                // {
                //     isExit = false;
                //     _exit.UnSelect();
                // }
            }
            else
            {
                if (isOut)
                {
                    isOut = false;
                    // if (isExit)
                    // {
                    //     isExit = false;
                    //     _exit.UnSelect();
                    // }
                    Insert(currentItem, tmpIndex);
                    Refresh();
                    // _exit.gameObject.SetActive(false);
                }
                else
                {
                    for (var i = 0; i < list.Count; i++)
                    {
                        if (_in == i) continue;
                        if (In(list[i], x, y))
                        {
                            Remove(currentItem);
                            Insert(currentItem, i);
                            Refresh();
                            break;
                        }
                    }
                }
            }
        }

        private bool Exit(int x, int y)
        {
            if (y < exit.y + exit.height / 2 && y > exit.y - exit.height / 2 && x < exit.x + exit.width / 2 &&
                x > exit.x - exit.width / 2) return true;
            return false;
        }

        public bool OutTop(float i)
        {
            return i > top;
        }

        public bool OutBottom(float i)
        {
            return i < bottom;
        }

        public bool OutLeft(float i)
        {
            return i < left;
        }

        public bool OutRight(float i)
        {
            return i > right;
        }

        private bool Out(int x, int y)
        {
            if (vertical)
                if (x > width || x < width * -1)
                    return true;

            if (horizontal)
                if (y > height || y < height * -1)
                    return true;

            return false;
        }

        private bool In(DragItemHelper item, int x, int y)
        {
            if (vertical)
                if (y < item.y + item.height / 2 && y > item.y - item.height / 2)
                    return true;

            if (horizontal)
                if (x < item.x + item.width / 2 && x > item.x - item.width / 2)
                    return true;

            return false;
        }

        protected virtual void Insert(DragItemHelper item, int index)
        {
            if (index >= list.Count)
            {
                list.Add(item);
            }
            else
            {
                var l = new List<DragItemHelper>();
                for (var i = 0; i < list.Count; i++)
                {
                    if (index == i) l.Add(item);
                    l.Add(list[i]);
                }

                list = l;
            }
        }

        protected virtual void Remove(DragItemHelper item)
        {
            list.Remove(item);
        }

        public void StartDrag(int _in)
        {
            isExit = false;
            isOut = false;
            tmpIndex = _in;
            currentItem = list[tmpIndex];
        }

        public void EndDrag()
        {
            if (isExit)
            {
                Insert(currentItem, tmpIndex);
                currentItem.OnClear();
            }
            else if (isOut)
            {
                Insert(currentItem, tmpIndex);
            }
            else
            {
                currentItem.OnChange(tmpIndex);
            }

            Refresh();
            tmpIndex = -1;
            isOut = false;
            isExit = false;
            exit.gameObject.SetActive(false);
        }

        [Button]
        public void Refresh()
        {
            if (vertical)
            {
                float th = 0;
                var ah = height;
                if (isFull)
                {
                    ah = _height;
                    var ih = (_height - (num - 1) * space) / num;
                    for (var i = 0; i < list.Count; i++) list[i].height = ih;
                }

                for (var i = 0; i < list.Count; i++) th += list[i].height;
                var start = (ah - th - (list.Count - 1) * space) / 2;
                float _h = 0;
                for (var i = 0; i < list.Count; i++)
                {
                    var centerY = start + list[i].height / 2;
                    list[i].OnChange(0, centerY - ah / 2);
                    list[i].SetIndex(i);
                    start += list[i].height + space;
                    _h += list[i].height;
                }

                _h += (list.Count - 1) * space;
                if (isAuto) rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Vertical, _h);
            }

            if (horizontal)
            {
                float tw = 0;
                var aw = width;

                if (isFull)
                {
                    aw = _width;
                    var iw = (_width - (num - 1) * space) / num;
                    for (var i = 0; i < list.Count; i++) list[i].width = iw;
                }

                for (var i = 0; i < list.Count; i++) tw += list[i].width;
                var start = (aw - tw - (list.Count - 1) * space) / 2;
                float _w = 0;
                for (var i = 0; i < list.Count; i++)
                {
                    var centerX = start + list[i].width / 2;
                    list[i].OnChange(centerX - aw / 2, 0);
                    list[i].SetIndex(i);
                    start += list[i].width + space;
                    _w += list[i].width;
                }

                _w += (list.Count - 1) * space;
                if (isAuto) rectTransform.SetSizeWithCurrentAnchors(RectTransform.Axis.Horizontal, _w);
            }

            isChange = false;
        }

        public void RefreshWidthHeight(float w, float h)
        {
            _width = w;
            _height = h;
            Refresh();
        }
    }
}